
import { ArrayServiceTreeToArrOptions,ArrayServiceArrToTreeOptions } from "./array.type"
import { deepMergeKey } from "../other/deep";



const c = deepMergeKey({}, false, {
    deepMapName: 'deep',
    parentMapName: 'parent',
    idMapName: 'id',
    parentIdMapName: 'parent_id',
    childrenMapName: 'children',
    titleMapName: 'title',
    checkedMapname: 'checked',
    selectedMapname: 'selected',
    expandedMapname: 'expanded',
    disabledMapname: 'disabled'
})!;

/**
 * Convert tree structure to array structure
 *
 * 将树结构转换成数组结构
 * 用法:例子
 * let a = [{a: '1', children: [{c: '2', d: '3', children: [{f: '4',g: '5',children: [{ i: '6'}]}]}]}, {jj: 'cc',children: [{kk: '3123'}]}]
 * 
 * treeToArr(a, { deepMapName: 'deep', parentMapName: 'parent', cb: () => { console.log(1) } })
 * 结果：
 * [{a: '1', deep: 0, parent: null}, {c: '2', d: '3', deep: 1, parent: {…}},{f: '4', g: '5', deep: 2, parent: {…}},{i: '6', deep: 3, parent: {…}}, {jj: 'cc', deep: 0, parent: null}
,{kk: '3123', deep: 1, parent: {…}}]
 * 
 */
const treeToArr = <T extends object = any>(tree: readonly T[], options?: ArrayServiceTreeToArrOptions<T>): T[] => {

    const opt = {
        deepMapName: c.deepMapName,
        parentMapName: c.parentMapName,
        childrenMapName: c.childrenMapName,
        clearChildren: true,
        cb: null,
        ...options
    } as ArrayServiceTreeToArrOptions;


    const result: Array<{ [key: string]: any }> = [];
    const inFn = (list: ReadonlyArray<{ [key: string]: any }>, parent: T | null, deep: number = 0) => {
        for (const i of list) {
            console.log(i)
            i[opt.deepMapName!] = deep;
            i[opt.parentMapName!] = parent;
            if (opt.cb) {
                opt.cb(i, parent, deep);
            }
            result.push(i);
            const children = i[opt.childrenMapName!];
            if (children != null && Array.isArray(children) && children.length > 0) {
                inFn(children, i as T, deep + 1);
            }
            if (opt.clearChildren) {
                delete i[opt.childrenMapName!];
            }
        }
    }
    inFn(tree, null);
    return result as T[];

}


/**
 * Convert array structure to tree structure
 *
 * 数组转换成树数据
 */

const arrToTree  = < T extends object = any > (arr: readonly T[], options ?: ArrayServiceArrToTreeOptions<T>): T[] => {
    
    if (!Array.isArray(arr) || arr.length === 0) {
        return [];
    }
    const opt = {
        idMapName: c.idMapName,
        parentIdMapName: c.parentIdMapName,
        childrenMapName: c.childrenMapName,
        cb: null,
        ...options
    } as ArrayServiceArrToTreeOptions<T>;
    const tree: T[] = [];
    const childrenOf: { [key: string]: T[] } = {};
    let rootPid = opt.rootParentIdValue;
    const arrType = arr as ReadonlyArray<{ [key: string]: any }>;
    
    if (!rootPid) {
        const pids = arrType.map(i => i[opt.parentIdMapName!]);
        const emptyPid = pids.findIndex(w => w == null);
        rootPid = emptyPid !== -1 ? pids[emptyPid] : pids.sort()[0];
        
    }
    
    for (const item of arrType) {
        const id = item[opt.idMapName!];
        const pid = item[opt.parentIdMapName!];
        
        childrenOf[id] = childrenOf[id] || [];
       
        item[opt.childrenMapName!] = childrenOf[id];
        console.log(pid,rootPid)
        if (opt.cb) {
            opt.cb(item as T);
        }
        
        if (pid !== rootPid) {
            childrenOf[pid] = childrenOf[pid] || [];
            
            childrenOf[pid].push(item as T);
        } else {
            tree.push(item as T);
        }
    }
    return tree;
}



export { treeToArr,arrToTree }